# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

import random
from odoo import fields, models, api

import logging
_logger = logging.getLogger(__name__)


def transfer_value(value, sensor_type_code):
    if sensor_type_code == 'moisture':
        return value / 10000
    else:
        return value


class IotSensorType(models.Model):
    _name = "iot.sensor.type"
    _description = 'IotSensorType'
    _order = "name"

    name = fields.Char(index=True, copy=False)
    code = fields.Char(index=True, copy=False)

    # a field for uom should be defined
    # uom

    _sql_constraints = [
        ('unique_code', 'UNIQUE (code)',  'code is unique!')
    ]

    @api.model
    def search_by_code(self, code):
        return self.search([('code', '=', code)])


class IotSensor(models.Model):
    _name = "iot.sensor"
    _description = 'IotSensor'
    _order = "name"

    name = fields.Char(index=True)
    code = fields.Char(index=True)

    user_id = fields.Many2one('res.users', 'User', related='device_id.user_id')
    partner_id = fields.Many2one(
        'res.partner', 'Partner', related='device_id.partner_id')
    company_id = fields.Many2one('res.company', related='device_id.company_id')
    project_id = fields.Many2one('iot.project', related='device_id.project_id')
    gateway_id = fields.Many2one('iot.gateway', related='device_id.gateway_id')
    device_id = fields.Many2one(
        'iot.device', 'Device', ondelete='cascade', index=True)

    sensor_type_id = fields.Many2one(
        'iot.sensor.type', 'Sensor Type', ondelete='restrict', index=True)

    latitude = fields.Float(string='Latitude', digits=(
        16, 5), related='device_id.latitude')
    longitude = fields.Float(string='Longitude', digits=(
        16, 5), related='device_id.longitude')

    depth = fields.Integer(string='Depth', default=0, help="UOM mm")

    value_ids = fields.One2many('iot.value', 'sensor_id', string='Values')

    # value = fields.Integer(
    #     string='Value', compute="_compute_value", store=True, help="UOM mm")
    # time = fields.Datetime(
    #     string="check Time", compute="_compute_value", store=True)

    # def _compute_value(self):
    #     for rec in self:
    #         value_id = self.value_ids.search(
    #             [['id', 'in', rec.value_ids.ids]], limit=1, order="id desc")
    #         rec.value = value_id and value_id.value or 0
    #         rec.time = value_id.time

    value = fields.Integer(string='Value',  help="UOM mm")
    time = fields.Datetime(string="check Time")

    value2 = fields.Float(
        string='Value2', compute="_compute_value2", store=True, help="UOM mm")

    @api.depends('value')
    def _compute_value2(self):
        # 根据 sensor_type_id , 做 value 转换, value 为 采样数据 integer
        for rec in self:
            rec.value2 = transfer_value(rec.value, rec.sensor_type_id.code)

    def _set_value(self):
        value_id = self.value_ids.search(
            [['id', 'in', self.value_ids.ids]], limit=1, order="id desc")
        self.value = value_id and value_id.value or 0
        self.time = value_id.time

    _sql_constraints = [
        ('unique_code', 'UNIQUE (code)',  'code is unique!')
    ]

    @api.model
    def search_by_code(self, code):
        return self.search([('code', '=', code)])

    soil_type_id = fields.Many2one(
        'iot.soil.type', related='project_id.soil_type_id')
    crop_type_id = fields.Many2one(
        'iot.crop.type', related='project_id.crop_type_id')

    mad = fields.Float(
        string='Management Allowable Depletion', related='project_id.mad')

    field_capacity = fields.Float(
        string='Field Capacity', related="project_id.field_capacity")

    total_available_water = fields.Float(
        string='Total Available Water', related="project_id.total_available_water")

    pwp = fields.Float(
        string='pwp', related="project_id.pwp")


class IotValue(models.Model):
    _name = "iot.value"
    _description = 'IotValue'
    _order = "time desc, id desc"

    @api.model
    def default_etl_timestamp(self):
        now = fields.Datetime.now().timestamp()
        now2 = round(now)
        return now2

    etl_timestamp = fields.Integer(string="Etl Time", required=True,
                                   default=default_etl_timestamp)
    code = fields.Char(index=True, required=True)
    name = fields.Char(related='code', string="Name")

    time = fields.Datetime(string="Check Time")

    user_id = fields.Many2one(
        'res.users', 'User', related='project_id.user_id')
    partner_id = fields.Many2one(
        'res.partner', 'Partner', related='project_id.partner_id')
    company_id = fields.Many2one(
        'res.company', related='project_id.company_id')
    project_id = fields.Many2one('iot.project', ondelete='cascade')

    gateway_id = fields.Many2one('iot.gateway',)
    device_id = fields.Many2one('iot.device', 'Device', index=True)
    sensor_id = fields.Many2one('iot.sensor', 'Sensor', index=True)

    sensor_type_id = fields.Many2one(
        'iot.sensor.type', 'Sensor Type', index=True)

    latitude = fields.Float(string='Latitude', digits=(16, 5))
    longitude = fields.Float(string='Longitude', digits=(16, 5))
    depth = fields.Integer(string='Depth', default=0, help="UOM mm")
    value = fields.Integer(string='Value', default=0, help="UOM mm")
    value2 = fields.Float(
        string='Value2', compute="_compute_value2", store=True, help="UOM mm")

    @api.depends('value')
    def _compute_value2(self):
        # 根据 sensor_type_id , 做 value 转换, value 为 采样数据 integer
        for rec in self:
            rec.value2 = transfer_value(rec.value, rec.sensor_type_id.code)

    _sql_constraints = [
        ('unique_code_etl', 'UNIQUE (code, etl_timestamp)',
         'code and etl_timestamp is unique!')
    ]

    @api.model
    def update_or_create(self, values):
        code = values.get('code')
        etl = values.get('etl_timestamp')
        domain = [('code', '=', code), ('etl_timestamp', '=', etl)]
        obj = self.search(domain)

        if obj:
            obj.write(values)
        else:
            obj = self.create(values)

        # to set sensor_id value, so query fast
        obj.sensor_id._set_value()

        return obj

    @api.model
    def create(self, values):
        code = values.get('code')
        domain = [('code', '=', code)]
        sensor = self.env['iot.sensor'].search(domain)
        if not sensor:
            return self

        values2 = {
            'etl_timestamp': values.get('etl_timestamp'),
            'code': sensor.code,
            'sensor_id': sensor.id,
            'device_id': sensor.device_id.id,
            'gateway_id': sensor.gateway_id.id,
            'project_id': sensor.project_id.id,
            'latitude': sensor.latitude,
            'longitude': sensor.longitude,
            'sensor_type_id': sensor.sensor_type_id.id,
            'depth': sensor.depth,
            'time': values.get('time'),
            'value': values.get('value'),
        }
        return super(IotValue, self).create(values2)

    # No used , 2020-07-24
    @api.model
    def update_values(self, sensors):

        value_list = []

        for sensor in sensors:
            sensor_id = self.sensor_id.search_by_code(sensor.get('code'))

            if not sensor_id:
                # server and gateway is not same config.
                continue

            values = {
                'code': sensor.get('code'),
                'sensor_id': sensor_id.id,
                'device_id': sensor_id.device_id.id,
                'gateway_id': sensor_id.gateway_id.id,
                'project_id': sensor_id.project_id.id,
                'latitude': sensor_id.latitude,
                'longitude': sensor_id.longitude,
                'sensor_type_id': sensor_id.sensor_type_id.id,
                'depth': sensor_id.depth,
                'time': sensor.get('time'),
                'value': sensor.get('value'),
            }

            value_list.append(values)

        if value_list:
            return self.create(value_list)

        return self

    @api.model
    def action_sensor(self):
        sensors = self.env['iot.sensor'].search([])

        now = fields.Datetime.now().timestamp()
        now2 = round(now)

        for sensor in sensors:
            values = {
                'etl_timestamp': now2,
                'code': sensor.code,
                'sensor_id': sensor.id,
                'device_id': sensor.device_id.id,
                'gateway_id': sensor.gateway_id.id,
                'project_id': sensor.project_id.id,
                'latitude': sensor.latitude,
                'longitude': sensor.longitude,
                'sensor_type_id': sensor.sensor_type_id.id,
                'depth': sensor.depth,
                'time': fields.Datetime.now(),
                'value': random.randint(10, 100),
            }

            self.create(values)
